#include <tshark_datatype.h>
#include <ip2regionUtil.h>
#include <iostream>

namespace Tshark
{
    auto &tshark_error_category()
    {
        static const struct : public std::error_category
        {

            virtual std::string message(int val) const
            {
                switch (error_code(val))
                {
                case error_code::success:
                    return "success";
                case error_code::file_not_exits:
                    return "file_not_exits";
                case error_code::file_open_failed:
                    return "file_open_failed";
                case error_code::parse_error:
                    return "parse_error";
                case error_code::failed:
                    return "failed";
                case error_code::out_of_range:
                    return "out_of_range";
                case error_code::popen_failed:
                    return "popen_failed";
                case error_code::parse_pcap_failed:
                    return "parse_pcap_failed";
                default:
                    return "unknown error";
                }
            }
            virtual const char *name() const noexcept
            {
                return "tshark";
            }
        } instance;
        return instance;
    }

    std::error_code make_error_code(error_code ec)
    {
        return std::error_code(int(ec), tshark_error_category());
    }

    namespace DataType
    {
        ParseResult Packet::parseLine(std::string line)
        {
            // 0: frame.number
            // 1: frame.time
            // 2: frame.cap_len
            // 3: ip.src
            // 4: ipv6.src
            // 5: ip.dst
            // 6: ipv6.dst
            // 7: tcp.srcport
            // 8: udp.srcport
            // 9: tcp.dstport
            // 10: udp.dstport
            // 11: _ws.col.Protocol
            // 12: _ws.col.Info
            // 13: len
            // 14: eth.src
            // 15: eth.dst

            ParseResult result;
            if (line.back() == '\n')
            {
                line.pop_back();
            }
            std::stringstream ss(line);
            std::vector<std::string> elems;
            std::string err_msg;
            std::size_t end, start = 0;
            while ((end = line.find('\t', start)) != std::string::npos)
            {
                elems.emplace_back(std::string(line.begin() + start, line.begin() + end));
                start = end + 1;
            }
            elems.emplace_back(line.substr(start));

            if (elems.size() >= 16)
            {
                result.code = parse_erroc::success;
                this->frame_number = std::stoi(elems[0]);
                this->time = std::atof(elems[1].c_str());
                this->cap_len = std::stoi(elems[2]);
                this->src_ip = elems[3].empty() ? elems[4] : elems[3];
                auto regionRes = Util::Ip2RegionUtil::getIpLocation(this->src_ip);
                if (regionRes)
                {
                    this->src_location = regionRes.location;
                }
                this->dst_ip = elems[5].empty() ? elems[6] : elems[5];
                regionRes = Util::Ip2RegionUtil::getIpLocation(this->dst_ip);
                if (!elems[8].empty() || !elems[7].empty())
                {
                    this->src_port = std::stoi(elems[7].empty() ? elems[8] : elems[7]);
                }
                if (regionRes)
                {
                    this->dst_location = regionRes.location;
                }
                if (!elems[9].empty() || !elems[10].empty())
                {
                    this->dst_port = std::stoi(elems[9].empty() ? elems[10] : elems[9]);
                }
                this->protocol = elems[11];
                this->info = elems[12];
                this->len = std::stoi(elems[13]);
                this->src_mac = elems[14];
                this->dst_mac = elems[15];
            }
            else
            {
                result.err_msg = err_msg;
            }
            return result;
        }

        std::string Packet::to_string() const
        {
            Json::Value result = this->to_json();
            Json::StreamWriterBuilder builder;
            // builder["emitUTF8"] = true; // 指定jsoncpp中文编码，这里直接修改了jsoncpp的源码，所以不用设置了
            const std::string jsonStr = Json::writeString(builder, result);
            return jsonStr;
        }

        Json::Value Packet::to_json() const
        {
            Json::Value result;
            result["file_offset"] = this->file_offset;
            result["frame_number"] = this->frame_number;
            result["time"] = this->time;
            result["cap_len"] = this->cap_len;
            result["src_ip"] = this->src_ip;
            result["src_port"] = this->src_port;
            result["dst_ip"] = this->dst_ip;
            result["dst_port"] = this->dst_port;
            result["protocol"] = this->protocol;
            result["info"] = this->info;
            result["file_offset"] = this->file_offset;
            result["src_location"] = this->src_location;
            result["dst_location"] = this->dst_location;
            result["len"] = this->len;
            result["src_mac"] = this->src_mac;
            result["dst_mac"] = this->dst_mac;
            return result;
        }

        const char *protocolStrErr(parse_erroc ec)
        {
            switch (ec)
            {
            case parse_erroc::success:
                return "协议解析成功！";
            default:
                return "协议解析失败！";
            }
        }

        auto &protocolErrocCategory()
        {
            const static struct : public std::error_category
            {
                virtual const char *name() const noexcept
                {
                    return "protocol";
                }

                /// @brief
                /// @param val
                /// @return
                virtual std::string message(int val) const
                {
                    return protocolStrErr((parse_erroc)val);
                }
            } instance;
            return instance;
        }

        std::error_code make_error_code(const parse_erroc &ec)
        {
            return std::error_code((int)ec, protocolErrocCategory());
        }

        ParseResult readPacketHex(const std::string &PcapFile, uint32_t offset, uint16_t length, std::vector<unsigned char> &buffer)
        {
            ParseResult result;
            std::ifstream file(PcapFile, std::ios::binary | std::ios::ate); // 设置ate，文件指针移动到文件尾部，用于获取文件大小
            if (!file)
            {
                result.code = parse_erroc::failed;
                return result;
            }
            std::streamsize fileSize = file.tellg(); // 获取文件大小
            if (offset + length > fileSize)
            {
                file.close();
                result.code = parse_erroc::failed;
                return result;
            }
            // 设置文件偏移为begin+offset
            file.seekg(offset, std::ios::beg);
            file.read(reinterpret_cast<char *>(buffer.data()), length);
            // std::cout << file.gcount() << std::endl;
            file.close();
            result.code = parse_erroc::success;
            return result;
        }

        AdapterMonitorInfo::AdapterMonitorInfo() : monitorThread(nullptr), tstarkPid(0)
        {
        }

    }
}